﻿namespace Bowlus.Common
{
    using System;
    using System.Collections.ObjectModel;
    using System.IO;
    using System.Linq;

    using Ionic.Zip;

    using Microsoft.WindowsAzure;
    using Microsoft.WindowsAzure.ServiceRuntime;
    using Microsoft.WindowsAzure.StorageClient;

    // TODO: Implement cache features
    public sealed class StorageAppRepository : IAppRepository
    {
        private readonly CloudBlobContainer appContainer;
        private readonly CloudBlobContainer customizationContainer;

        public StorageAppRepository(string configuration)
        {
            this.appContainer = CloudStorageAccount.Parse(RoleEnvironment.GetConfigurationSettingValue(configuration)).CreateCloudBlobClient().GetContainerReference(Settings.AppContainer);
            this.customizationContainer = CloudStorageAccount.Parse(RoleEnvironment.GetConfigurationSettingValue(configuration)).CreateCloudBlobClient().GetContainerReference(Settings.CustomizationContainer);
        }

        // Used for uploading a new application
        public void Upload(string name, MemoryStream stream)
        {
            // TODO: implement this
        }

        public Collection<string> GetCustomizationList(string appName)
        {
            var blobs = this.customizationContainer.ListBlobs();
            var filteredBlobs = (from b in blobs
                                 where b.Uri.AbsolutePath.IndexOf(appName, StringComparison.InvariantCultureIgnoreCase) >= 0
                                 select Path.GetFileName(b.Uri.ToString())).ToArray();

            return new Collection<string>(filteredBlobs);
        }

        public Collection<string> GetAppList()
        {
            var blobs = this.appContainer.ListBlobs();

            // Create a dictionary for dropdown list
            var dict = blobs.Select(app => Path.GetFileName(app.Uri.ToString())).ToDictionary(s => s);

            var appList = new Collection<string>();
            foreach (var item in dict)
            {
                appList.Add(item.Value);
            }

            return appList;
        }

        public MemoryStream DownloadApp(string name)
        {
            var blob = this.appContainer.GetBlobReference(name);
            var st = new MemoryStream();
            blob.DownloadToStream(st);

            return st;
        }

        public MemoryStream GetTenantCustomization(string tenantid)
        {
            return new MemoryStream();
        }

        public void ExtractTenantApplication(TenantDeployment tenantDeployment, string destination)
        {
            var blob = this.appContainer.GetBlobReference(tenantDeployment.Application);

            using (var stream = new MemoryStream())
            {
                blob.DownloadToStream(stream);
                stream.Position = 0;

                using (var zipFile = ZipFile.Read(stream))
                {
                    zipFile.ExtractAll(destination);
                }
            }

            if (tenantDeployment.IncludesCustomizations)
            {
                this.WriteCustomizationsTo(tenantDeployment, destination);
            }
        }

        private void WriteCustomizationsTo(TenantDeployment td, string destination)
        {
            var customizations = td.GetCustomizations();
            foreach (var blob in customizations.Select(item => this.customizationContainer.GetBlobReference(item)))
            {
                using (var stream = new MemoryStream())
                {
                    blob.DownloadToStream(stream);

                    using (var zipFile = ZipFile.Read(stream))
                    {
                        zipFile.ExtractAll(destination);
                    }
                }
            }
        }
    }
}
